先在index.html.erb加上編輯的連結
<h1>Hello World!!</h1>
<%= link_to "新增",new_book_path %>
<% @books.each do |book|%>
<%= link_to book.title,book_path %>
<%= link_to "編輯",edit_book_path(book) %>
<% end%>
```html
edit_book_path後面加上(book),讓他找得到book的id。
回到controller寫edit的action
```ruby
def edit
@book = Book.find(params[:id])
end
有沒有覺得很熟悉,沒錯直接複製show的就好了,他們都是去找特定id的頁面。
再來寫update的action,一樣也是複製貼上,這次複製create的內容,再一點點修改。
def update
@book = Book.find(params[:id])
if @book.update(book_params)
redirect_to books_path
else
render :edit
end
end
update的資料要先清洗過,render換成edit頁面。
再來寫view,建立edit.html.erb
<h1>編輯</h1>
<%= form_with model:@book do |form| %>
<div>標題:<%=form.text_field :title %></div>
<div>內容:<%=form.text_area :content %></div>
<div>價錢:<%=form.text_field :price %></div>
<%= form.submit "編輯商品"%>
<% end %>
有沒有覺得很眼熟,沒錯,跟new的view一樣,複製貼上換上編輯看個字而已。
這兩個的code重複使用的時候,可以建立一個檔案,讓他們去render。
建立_form.html.erb。名字可隨意取,但是最前面要加上_
<%= form_with model:book do |form| %>
<div>標題:<%=form.text_field :title %></div>
<div>內容:<%=form.text_area :content %></div>
<div>價錢:<%=form.text_field :price %></div>
<%= form.submit %>
<% end %>
注意的兩點,把實體變數變成一般的變數,@book => book 。
再來是submit的內容因為略有不同,所以刪掉讓submit自動生字。
這時候的new.html.erb/edit.html.erb
<h1>新增</h1>
<%= render "form", book: @book %>
<h1>編輯</h1>
<%= render "form", book: @book %>
render _form.html.erb的內容,然後將變數book指定成@book。
先在index的view寫上刪除的連結
<h1>Hello World!!</h1>
<%= link_to "新增",new_book_path %>
<% @books.each do |book|%>
<%= link_to book.title,book_path %>
<%= link_to "編輯",edit_book_path(book) %>
<%= link_to "刪除",book_path %>
<% end%>
當你點擊刪除的時候,你會發現你的網頁會跑向show的頁面。
rails routes明明寫著Perfix也是book。
在這裡show/update/destroy都是共用book_path,我們要再後面加上method,來區分它們。
<h1>Hello World!!</h1>
<%= link_to "新增",new_book_path %>
<% @books.each do |book|%>
<%= link_to book.title,book_path %>
<%= link_to "編輯",edit_book_path(book) %>
<%= link_to "刪除",book_path,method: "delete" %>
<% end%>
為了避免使用者按了就直接刪除,給他加一個警告確認
book_path可以簡寫成book
<h1>Hello World!!</h1>
<%= link_to "新增",new_book_path %>
<% @books.each do |book|%>
<%= link_to book.title,book %>
<%= link_to "編輯",edit_book_path(book) %>
<%= link_to "刪除",book,method: "delete" ,data: {confirm: "是否刪除?"} %>
<% end%>
按下去後看到眼熟的紅色框框,Unknown action,代表我們做對方向了,補上destroy action
class BooksController < ApplicationController
def destroy
@book = Book.find(params[:id])
@book.destroy
redirect_to books_path
end
end
這樣刪除就完成了,到這邊CRUD的功能已經具備,但是如果仔細一看,會發現@book = Book.find(params[:id])
這行code一直不斷重複使用。
當你相同的東西一直重複使用的時候,就應該把他寫成一個方法,讓大家都能使用。
private
def find_book
@book = Book.find(params[:id])
end
但是如果只是這樣還不夠,難道我們要一直重複呼喚這個方法。
在Rails有一個寫法叫做before_action,他會讓方法直接默認的在action裡使用過,不用在多個action一直重複寫這方法。
before_action放在最上面,要在action之前執行
class BooksController < ApplicationController
before_action :find_book,only: [:show, :edit, :update, :destroy]
def index
@books = Book.order(id: :desc)
end
.
.
.
end
before_action有兩種寫法,only是只有這些action執行方法,另一個except則是除了這些action以外通通都要執行。
[:show, :edit, :update, :destroy]
這四個action的@book = Book.find(params[:id])
就可以刪掉了。